package com.daiqee.util;
import java.lang.reflect.Field;

import java.text.SimpleDateFormat;

import java.util.Date;

import org.apache.commons.lang3.StringUtils;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.daiqee.annotations.DateField;

/**
 *  MyBatis-Plus 工具类
 * 
 * <br/>
 * @since JDK 1.8
 * @version  V2.1
 * @author RichardTang 
 * @date: 2018年5月7日 下午5:59:52
 * @package com.daiqee.util
 * @copyright:Copyright (c) 2018, 1245811923@qq.com All Rights Reserved.
 */
public class MyBatisPlusUtils {
	
	/**
	 * 给定一个格式为 <b>2018年4月19日11:48:24 - 2018年4月19日11:48:30</b> <br/>
	 * 格式的日期 来拼接一个 日期范围的查询条件 <br/>
	 * t:这里的实体的成员属性值也会默认作为查询条件
	 * 
	 * @param t
	 * 		  实体
	 * 
	 * @param dateScope
	 * 			 日期值
	 * 
	 * @param timeField
	 *			数据库日期字段 		
	 *
	 * @return 条件
	 */			
	public static <T> EntityWrapper<T> getTimeScopeCondition(T t,String dateScope,String timeField){
		
		EntityWrapper<T> ew = new EntityWrapper<T>(t);
		
		if(dateScope != "" && dateScope != null) {
			
			//切割日期范围 开始日期 - 结束日期
			String[] split = dateScope.split(" - ");
			
			//添加查询条件
			ew.between(timeField, split[0], split[1]);
		}
		
		return ew;
	}
	
	/**
	 * 生成Mybatis-plust提供的EntityWrapper条件实体
	 * 
	 * 注意这里需要传入的Entity实体指明日期属性,在日期属性上添加 @DateField 属性
	 * 
	 * @DateField 代表用来查询日期范围的字段,属性命名必须使用驼峰命名法,并且要与数据库中的字段对应
	 * 
	 * @param entity
	 * 			条件实体,会根据entity的属性来当做查询条件
	 * @param queryOfDateScope
	 * 			查询的数据的日期范围
	 */
	public static <E> EntityWrapper<E> generatorEntityWrapperByEntityAndDateScope (E entity,String queryOfDateScope){
		
		EntityWrapper<E> ew = new EntityWrapper<E>(entity);
		
		if(queryOfDateScope != "" && queryOfDateScope != null) {
			
			//拿到日期属性字符
			String dateFieldStr = getDateFieldName(entity.getClass());
			
			//如果没有日期属性则不拼接 查询日期范围这个条件
			if(StringUtils.isNotEmpty(dateFieldStr)) {
				//切割日期范围 开始日期 - 结束日期
				String[] split = queryOfDateScope.split(" - ");
				
				//添加查询条件
				ew.between(dateFieldStr, split[0], split[1]);
			}
		}
		
		return ew;
	}
	
	/**
	 * 单号前后缀拼接
	 * @param suffix
	 * 			01 = 入库单号 , 02 = 出库单号
	 */
	private static String orderNumberPerfix(String suffix) {
		return new SimpleDateFormat("yyyyMMddHHmmss01").format(new Date()).toString() + suffix;
	}
	
	/**
	 * 生成入库订单号
	 */
	public static String getInOrderNumber() {
		return orderNumberPerfix("01");
	}
	
	/**
	 * 生成出库订单号
	 */
	public static String getOutOrderNumber() {
		return orderNumberPerfix("02");
	}
	
	/**
	 * 通过反射拿到成员属性中@DateField的属性名
	 */
	@SuppressWarnings("rawtypes")
	public static String getDateFieldName(Class clazz) {
		//获取成员属性
		Field[] fields = clazz.getDeclaredFields();
		//循环遍历判断属性名,找到@DateField为止
		for(int i = 0; i < fields.length; i++) {
			if(fields[i].getAnnotation(DateField.class) != null) {
				//找到使用了@DateField注解的属性
				String fieldName = fields[i].getName();
				//将驼峰命名法转成下划线命名法,因为数据库字段存储的格式就是下划线命名
				return HumpToUnderline(fieldName);
			}
		}
		//当都循环完完毕,没有找到就代表没有使用DateField注解
		return null;
	}
	
	/***
	 * 下划线命名转为驼峰命名
	 * 
	 * @param para
	 *        下划线命名的字符串
	 */
    public static String UnderlineToHump(String para){
        StringBuilder result=new StringBuilder();
        String a[]=para.split("_");
        for(String s:a){
            if(result.length()==0){
                result.append(s.toLowerCase());
            }else{
                result.append(s.substring(0, 1).toUpperCase());
                result.append(s.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }

	/***
	 * 驼峰命名转为下划线命名
	 * 
	 * @param para
	 *        驼峰命名的字符串
	 */
    public static String HumpToUnderline(String para){
            StringBuilder sb=new StringBuilder(para);
            int temp=0;//定位
            for(int i=0;i<para.length();i++){
                if(Character.isUpperCase(para.charAt(i))){
                    sb.insert(i+temp, "_");
                    temp+=1;
                }
            }
            return sb.toString().toUpperCase(); 
    }
	
}
